"""
工具函数模块 - 用于处理查询结果为0条时的自动扩展查询功能
"""

import logging
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple


class QueryExpander:
    """查询扩展器 - 用于处理查询结果为0条时的自动扩展查询功能"""
    
    @staticmethod
    def calculate_half_year_range(start_date: str, end_date: str) -> Tuple[str, str]:
        """
        计算半年前的时间范围
        
        Args:
            start_date: 开始日期 (格式: YYYYMMDD)
            end_date: 结束日期 (格式: YYYYMMDD)
            
        Returns:
            Tuple[str, str]: 半年前的开始日期和结束日期
        """
        try:
            # 将字符串日期转换为datetime对象
            start_dt = datetime.strptime(start_date, "%Y%m%d")
            end_dt = datetime.strptime(end_date, "%Y%m%d")
            
            # 计算半年前的日期
            half_year_ago = start_dt - timedelta(days=180)
            
            # 确保半年前的日期不会太早（比如早于系统支持的最早日期）
            # 这里可以设置一个最小日期限制，比如2020年1月1日
            min_date = datetime(2020, 1, 1)
            if half_year_ago < min_date:
                half_year_ago = min_date
            
            # 计算半年前时间段的结束日期（通常是原开始日期的前一天）
            half_year_end = start_dt - timedelta(days=1)
            
            # 格式化返回日期
            half_year_start_str = half_year_ago.strftime("%Y%m%d")
            half_year_end_str = half_year_end.strftime("%Y%m%d")
            
            logging.info(f"[查询扩展] 计算半年前时间范围: {half_year_start_str} 至 {half_year_end_str}")
            
            return half_year_start_str, half_year_end_str
            
        except Exception as e:
            logging.error(f"[查询扩展] 计算半年前时间范围失败: {str(e)}")
            # 如果计算失败，返回一个默认的半年范围
            try:
                start_dt = datetime.strptime(start_date, "%Y%m%d")
                half_year_ago = start_dt - timedelta(days=180)
                half_year_end = start_dt - timedelta(days=1)
                
                return half_year_ago.strftime("%Y%m%d"), half_year_end.strftime("%Y%m%d")
            except:
                # 如果还是失败，返回空字符串
                return "", ""
    
    @staticmethod
    def find_nearest_data_date(data_list: List[Dict], target_date: str, date_field: str) -> Optional[Dict]:
        """
        查找离目标日期最近的记录
        
        Args:
            data_list: 数据列表
            target_date: 目标日期
            date_field: 日期字段名
            
        Returns:
            Optional[Dict]: 最近的记录
        """
        if not data_list or not target_date:
            return None
            
        try:
            # 根据目标日期长度确定日期格式
            if len(target_date) == 8 and target_date.isdigit():
                target_dt = datetime.strptime(target_date, "%Y%m%d")
            elif len(target_date) == 6 and target_date.isdigit():
                # YYYYMM格式，转换为当月第一天
                target_dt = datetime.strptime(target_date + "01", "%Y%m%d")
            else:
                logging.error(f"[查询扩展] 不支持的目标日期格式: {target_date}")
                return None
            
            nearest_record = None
            min_days_diff = float('inf')
            
            for record in data_list:
                record_date_str = record.get(date_field)
                if not record_date_str:
                    continue
                    
                try:
                    # 根据记录日期长度确定日期格式
                    if len(record_date_str) == 8 and record_date_str.isdigit():
                        record_dt = datetime.strptime(record_date_str, "%Y%m%d")
                    elif len(record_date_str) == 6 and record_date_str.isdigit():
                        # YYYYMM格式，转换为当月第一天
                        record_dt = datetime.strptime(record_date_str + "01", "%Y%m%d")
                    else:
                        logging.warning(f"[查询扩展] 不支持的记录日期格式: {record_date_str}")
                        continue
                        
                    days_diff = abs((record_dt - target_dt).days)
                    
                    if days_diff < min_days_diff:
                        min_days_diff = days_diff
                        nearest_record = record
                        
                except Exception as e:
                    logging.warning(f"[查询扩展] 解析记录日期失败: {record_date_str}, 错误: {str(e)}")
                    continue
            
            if nearest_record:
                logging.info(f"[查询扩展] 找到离目标日期最近的记录，日期差: {min_days_diff}天")
            else:
                logging.info(f"[查询扩展] 未找到有效的日期记录")
                
            return nearest_record
            
        except Exception as e:
            logging.error(f"[查询扩展] 查找最近日期记录失败: {str(e)}")
            return None
    
    @staticmethod
    def format_nearest_date_message(nearest_record: Dict, query_type: str, original_params: Dict, date_field: str = "endDate") -> str:
        """
        格式化最近日期信息的消息
        
        Args:
            nearest_record: 最近的记录
            query_type: 查询类型 ('invoice', 'sett', 'etc_invoice' 或 'etc_sett')
            original_params: 原始查询参数（包含用户查询的日期范围）
            date_field: 日期字段名
            
        Returns:
            str: 格式化的消息
        """
        if not nearest_record:
            return ""
            
        record_date = nearest_record.get(date_field, "未知")
        
        # 获取用户查询的日期范围
        user_start_date = original_params.get('startDate', '未知')
        user_end_date = original_params.get('endDate', '未知')
        
        # 格式化日期显示（如果日期格式是YYYYMMDD，转换为YYYY-MM-DD；如果是YYYYMM，转换为YYYY-MM）
        if len(user_start_date) == 8 and user_start_date.isdigit():
            user_start_date = f"{user_start_date[:4]}-{user_start_date[4:6]}-{user_start_date[6:8]}"
        elif len(user_start_date) == 6 and user_start_date.isdigit():
            user_start_date = f"{user_start_date[:4]}-{user_start_date[4:6]}"
            
        if len(user_end_date) == 8 and user_end_date.isdigit():
            user_end_date = f"{user_end_date[:4]}-{user_end_date[4:6]}-{user_end_date[6:8]}"
        elif len(user_end_date) == 6 and user_end_date.isdigit():
            user_end_date = f"{user_end_date[:4]}-{user_end_date[4:6]}"
        
        date_range_info = f"（用户查询的日期范围：{user_start_date} 至 {user_end_date}）"
        
        if query_type == "invoice":
            amount = nearest_record.get("amountWithTax", "0")
            return f"\n\n**提示**: 在您查询的时间范围内未找到发票记录{date_range_info}。系统已自动往前查询半年数据，发现离您查询日期最近的发票记录是 **{record_date}** 的发票，含税金额为 **{amount}** 元。"
        
        elif query_type == "sett":
            start_date = nearest_record.get("startDate", "未知")
            end_date = nearest_record.get("endDate", "未知")
            tb_no = nearest_record.get("tbNo", "未知")
            return f"\n\n**提示**: 在您查询的时间范围内未找到轧差表记录{date_range_info}。系统已自动往前查询半年数据，发现离您查询日期最近的轧差表是 **{tb_no}**，日期范围为 **{start_date} 至 {end_date}**。"
        
        elif query_type == "etc_invoice":
            amount = nearest_record.get("jshj", "0")
            merchant_name = nearest_record.get("kpMerName", "未知")
            return f"\n\n**提示**: 在您查询的时间范围内未找到ETC发票记录{date_range_info}。系统已自动往前查询半年数据，发现离您查询日期最近的ETC发票记录是 **{record_date}** 的发票，商户为 **{merchant_name}**，价税合计为 **{float(amount)/100:.2f}** 元。"
        
        elif query_type == "etc_sett":
            start_date = nearest_record.get("startDate", "未知")
            end_date = nearest_record.get("endDate", "未知")
            sub_station = nearest_record.get("subStation", "未知")
            return f"\n\n**提示**: 在您查询的时间范围内未找到ETC结算记录{date_range_info}。系统已自动往前查询半年数据，发现离您查询日期最近的ETC结算记录是 **{sub_station}** 站点，日期范围为 **{start_date} 至 {end_date}**。"
        
        else:
            return f"\n\n**提示**: 在您查询的时间范围内未找到记录{date_range_info}。系统已自动往前查询半年数据，发现离您查询日期最近的记录日期是 **{record_date}**。"


async def expand_query_when_no_data(
    original_params: Dict,
    api_path: str,
    query_type: str,
    service_module,
    user_query: str = ""
) -> Tuple[Dict, Optional[Dict]]:
    """
    当查询结果为0条时，自动扩展查询范围并查找最近的数据
    
    Args:
        original_params: 原始查询参数
        api_path: API路径
        query_type: 查询类型 ('invoice' 或 'sett')
        service_module: 服务模块（包含call_api方法）
        user_query: 用户查询（用于日志记录）
        
    Returns:
        Tuple[Dict, Optional[Dict]]: (扩展查询结果, 最近的记录)
    """
    
    logging.info(f"[查询扩展] 开始处理查询扩展，查询类型: {query_type}")
    
    # 检查是否有必要的日期参数
    start_date = original_params.get('startDate')
    end_date = original_params.get('endDate')
    
    if not start_date or not end_date:
        logging.warning(f"[查询扩展] 缺少日期参数，无法进行扩展查询")
        return {}, None
    
    # 计算半年前的时间范围
    half_year_start, half_year_end = QueryExpander.calculate_half_year_range(start_date, end_date)
    
    if not half_year_start or not half_year_end:
        logging.error(f"[查询扩展] 计算半年前时间范围失败")
        return {}, None
    
    # 构建扩展查询参数
    expanded_params = original_params.copy()
    expanded_params['startDate'] = half_year_start
    expanded_params['endDate'] = half_year_end
    
    try:
        # 调用API进行扩展查询
        logging.info(f"[查询扩展] 开始扩展查询，时间范围: {half_year_start} 至 {half_year_end}")
        expanded_data = await service_module.call_api(api_path, expanded_params)
        
        if not isinstance(expanded_data, dict):
            logging.error(f"[查询扩展] 扩展查询API返回类型错误")
            return {}, None
        
        # 根据查询类型获取数据列表
        if query_type == "invoice":
            data_list = expanded_data.get('invoiceList', [])
            date_field = "endDate"
        elif query_type == "sett":
            data_list = expanded_data.get('settList', [])
            date_field = "startDate"  # 轧差表使用开始日期
        elif query_type == "etc_invoice":
            data_list = expanded_data.get('respData', expanded_data.get('etcMerInvoiceDtlList', []))
            date_field = "kpMonth"  # ETC发票使用开票月份
        elif query_type == "etc_sett":
            data_list = expanded_data.get('respData', expanded_data.get('resultDOS', []))
            date_field = "startDate"  # ETC结算使用开始日期
        else:
            logging.error(f"[查询扩展] 不支持的查询类型: {query_type}")
            return expanded_data, None
        
        logging.info(f"[查询扩展] 扩展查询获取到{len(data_list)}条记录")
        
        # 如果没有数据，直接返回
        if not data_list:
            logging.info(f"[查询扩展] 扩展查询范围内也未找到数据")
            return expanded_data, None
        
        # 查找离原始查询开始日期最近的记录
        nearest_record = QueryExpander.find_nearest_data_date(data_list, start_date, date_field)
        
        return expanded_data, nearest_record
        
    except Exception as e:
        logging.error(f"[查询扩展] 扩展查询失败: {str(e)}")
        return {}, None


async def enhance_no_data_response(
    original_response: Dict,
    original_params: Dict,
    api_path: str,
    query_type: str,
    service_module,
    user_query: str = ""
) -> Dict:
    """
    增强查询结果为0条时的响应，添加最近数据信息
    
    Args:
        original_response: 原始响应
        original_params: 原始查询参数
        api_path: API路径
        query_type: 查询类型 ('invoice' 或 'sett')
        service_module: 服务模块
        user_query: 用户查询
        
    Returns:
        Dict: 增强后的响应
    """
    
    # 首先检查是否有记录 - 这是最重要的判断条件
    records = original_response.get('records', [])
    if records:
        # 如果有记录，说明原始查询有数据，直接返回原始响应，不触发扩展查询
        return original_response
    
    # 然后检查原始响应是否表示没有数据
    summary = original_response.get('summary', '')
    
    # 更宽松的判断条件：只要summary包含"未找到"或"没有"等关键词，就触发扩展查询
    no_data_keywords = ['未找到', '没有', '无记录', '0条', '空结果']
    has_no_data_indicator = any(keyword in summary for keyword in no_data_keywords)
    
    # 如果summary为空，也认为是无数据情况
    if not summary.strip():
        has_no_data_indicator = True
    
    if not has_no_data_indicator:
        # 如果不是"未找到"的响应，直接返回原始响应
        return original_response
    
    logging.info(f"[响应增强] 检测到查询结果为0条，开始扩展查询")
    logging.info(f"[响应增强] 原始响应summary: {summary}")
    
    # 进行扩展查询
    expanded_data, nearest_record = await expand_query_when_no_data(
        original_params, api_path, query_type, service_module, user_query
    )
    
    if nearest_record:
        # 如果有最近的记录，增强响应消息
        enhanced_message = QueryExpander.format_nearest_date_message(nearest_record, query_type, original_params)
        
        # 将增强消息添加到summary中
        original_response['summary'] = summary + enhanced_message
        
        # 添加扩展查询的调试信息
        if original_response.get('debug_info'):
            original_response['debug_info']['expanded_query'] = {
                'expanded_data_count': len(expanded_data.get('invoiceList', []) if query_type == 'invoice' else expanded_data.get('settList', [])),
                'nearest_record_date': nearest_record.get('invoiceOpDate' if query_type == 'invoice' else 'startDate'),
                'expanded_time_range': f"{original_params.get('startDate')}半年前至{original_params.get('endDate')}前一天"
            }
        
        logging.info(f"[响应增强] 成功添加最近数据信息到响应中")
    else:
        logging.info(f"[响应增强] 扩展查询也未找到数据，保持原始响应")
    
    return original_response